package com.david.viewtest.view
import android.content.Context
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.VelocityTracker
import android.view.ViewConfiguration
import android.widget.FrameLayout
import android.widget.Scroller

/**
 * 可横向及纵向惯性滑动的view
 *
 * TODO 实现缩放查看大图逻辑； 及查看大图嵌套横向滑动列表
 */
class MyScrollAndFlingView(context: Context, attrs: AttributeSet): FrameLayout(context, attrs) {

    // 上一次触摸事件的y坐标
    private var lastX = 0f
    private var lastY = 0f
    // 用来算速度的工具（通过在每次的触摸事件中打点）
    private var mVelocityTracker: VelocityTracker = VelocityTracker.obtain()

    // 用来根据传入的速度算当前应该滚动到的位置的工具
    private val scroller by lazy { Scroller(context) }

    private var isActionUp = false
    private var eventCopy:MotionEvent? = null
    private var eventX = 0f
    private var eventY = 0f
    private var dx = 0f
    private var dy = 0f
    private var maxV = 0f
    private var xVelocity = 0f
    private var yVelocity = 0f
    override fun onTouchEvent(event: MotionEvent): Boolean {
        if (!scroller.isFinished) {
            scroller.abortAnimation();
        }
        if (!super.onTouchEvent(event)) {
            isActionUp = false
            // 拷贝一份触摸事件，我猜是为了防止污染原事件
            eventCopy = MotionEvent.obtain(event)

            eventX = event.x
            eventY = event.y

            when(event.actionMasked) {
                MotionEvent.ACTION_DOWN -> {
                    lastX = eventX
                    lastY = eventY
                }
                MotionEvent.ACTION_MOVE -> {
                    dx = lastX - eventX
                    dy = lastY - eventY
                    scrollTo((scrollX + dx).toInt(), (scrollY + dy).toInt())
                    lastX = eventX
                    lastY = eventY
                }
                MotionEvent.ACTION_UP -> {
                    // 最后一次打点
                    mVelocityTracker.addMovement(eventCopy)
                    isActionUp = true
                    // 设定一个最大速度，速度太快体验也不好
                    maxV = ViewConfiguration.get(context).scaledMaximumFlingVelocity.toFloat()
                    // 这里的 1000 是你想要的速度单位。值1提供像素/毫秒，1000提供像素/秒
                    mVelocityTracker.computeCurrentVelocity(1000, maxV)
                    xVelocity = -mVelocityTracker.getXVelocity(event.getPointerId(0))
                    yVelocity = -mVelocityTracker.getYVelocity(event.getPointerId(0))

                    startFling(xVelocity.toInt(), yVelocity.toInt())

                    mVelocityTracker.clear()
                }
                else -> {}
            }

            if (!isActionUp) {
                // 每次触摸事件打点
                mVelocityTracker.addMovement(eventCopy)
            }
            eventCopy?.recycle()

            return true
        }

        return false
    }

    private val refreshRunnable = Runnable {
        if (scroller.computeScrollOffset()) {
            scrollTo(scroller.currX, scroller.currY)
            postOnAnimationFun()
        }
    }

    private fun postOnAnimationFun() {
        // 使Runnable在下一个动画时间步长上执行
        postOnAnimation (refreshRunnable)
    }

    private fun startFling(velocityX: Int, velocityY: Int) {
        // 通知scroller开始计算应该活动到的位置
        scroller.fling(scrollX, scrollY, velocityX, velocityY, Int.MIN_VALUE, Int.MAX_VALUE, Int.MIN_VALUE, Int.MAX_VALUE)

        postOnAnimationFun()
    }

    private var realHeight = 0
    private var newY = 0
    override fun scrollTo(x: Int, y: Int) {
        realHeight = getRealHeight()
        newY = if (y < 0) 0
        else if (y > realHeight) realHeight
        else y
        super.scrollTo(x, newY)
    }

    private var tempHeight = 0
    private fun getRealHeight(): Int {
        tempHeight = 0
        for(index in 0 until childCount) {
            tempHeight += getChildAt(index).height
        }
        return tempHeight - this.height
    }
}
